package com.wits100.demoplayer;

import android.Manifest;
import android.app.DownloadManager;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.webkit.MimeTypeMap;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

import com.loopj.android.http.JsonHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import com.wits.util.NetUtil;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cz.msebera.android.httpclient.Header;



public class MainActivity extends AppCompatActivity {

    public final String TAG = "httpapi";

    private static final int PERMISSIONS_REQUEST_CODE_WRITE_EXTERNAL_STORAGE = 201;
    private static final int PERMISSIONS_REQUEST_CODE = 202;
    private static final int HTTP_PORT = 8000;


    private SimpleAdapter recordListAdapter;
    private List<Map<String, Object>> recordListData = new ArrayList<>();
    private HttpServer  httpServer;
    private Handler httpHandler;


    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
            = new BottomNavigationView.OnNavigationItemSelectedListener() {

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()) {
                case R.id.navigation_home:
                    fetchRecordList();
                    return true;
                case R.id.navigation_dashboard:
                    return true;
                case R.id.navigation_settings:
                    return true;
            }
            return false;
        }

    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);

        setupRecordList();
        setupUrlEdit();

        RestClient.client.setTimeout(3000);
        RestClient.client.setConnectTimeout(3000);
        RestClient.client.setResponseTimeout(3000);
        RestClient.client.setLoggingEnabled(true);
        RestClient.client.setLoggingLevel(Log.DEBUG);

        String baseUrl = getBaseUrl();
        //baseUrl = "http://192.168.2.22:8000/";
        initHttp(baseUrl);

        checkWriteExternalStoragePermission();
        checkPermission();

        setupHttp();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        teardownHttp();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        Log.i(TAG, "code: " + requestCode + " " + permissions);

        if (requestCode == PERMISSIONS_REQUEST_CODE_WRITE_EXTERNAL_STORAGE) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {

            } else {
                showToast("can not snap and download record.", Toast.LENGTH_LONG);
            }
        }

    }

    private void showToast(String message, int duration) {
        try {
            Toast.makeText(getApplicationContext(), message, duration).show();
        } catch (Throwable t) {
            //
        }
    }

    private void checkWriteExternalStoragePermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSIONS_REQUEST_CODE_WRITE_EXTERNAL_STORAGE);
            } else {
                //
            }
        }
    }


    private void checkPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.INTERNET}, PERMISSIONS_REQUEST_CODE);
            } else {
                //
            }

            if (checkSelfPermission(Manifest.permission.ACCESS_WIFI_STATE) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.ACCESS_WIFI_STATE, Manifest.permission.ACCESS_NETWORK_STATE}, PERMISSIONS_REQUEST_CODE);
            } else {
                //
            }
        }
    }

    protected void setupRecordList() {
        ListView listView = (ListView) findViewById(R.id.listViewRecord);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (position < recordListData.size()) {
                    Map<String,Object> record = recordListData.get(position);
                    onClickRecord(record);
                }
            }
        });

        listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long l) {
                if (position < recordListData.size()) {
                    Map<String,Object> record = recordListData.get(position);
                    onLongClickRecord(record);
                    return true;
                }
                return false;
            }
        });

        recordListAdapter = new SimpleAdapter(this, recordListData, R.layout.list_item_record,
                new String[]{"name"},
                new int[]{R.id.name});
        listView.setAdapter(recordListAdapter);
    }

    protected void setupUrlEdit() {
        EditText editText = (EditText)findViewById(R.id.editTextAddr);
        editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
                if (i == EditorInfo.IME_ACTION_DONE) {
                    Log.i(TAG, textView.getText().toString());
                    onBaseUrlChanged(textView.getText().toString());
                }
                return false;
            }
        });
    }

    protected void fetchRecordList() {

        Log.i(TAG, "begin fetch ...");

        String prefix = "api/getFileList";
        RequestParams params = new RequestParams();
        params.add("startTime", "0");
        params.add("endTime", "0");
        RestClient.get(prefix, params, new JsonHttpResponseHandler() {

            @Override
            public void onSuccess(int statusCode, Header[] headers, JSONObject result) {
                Log.i(TAG, "fetch done ...");

                JSONArray records = result.optJSONArray("object");

                recordListData.clear();

                for (int i = 0; i < records.length(); i ++) {
                    JSONObject jsonObject = records.optJSONObject(i);
                    if (jsonObject == null) {
                        break;
                    }

                    String name = jsonObject.optString("name");
                    int type = jsonObject.optInt("type", 0);

                    Map<String, Object> record = new HashMap<>();
                    record.put("name", name);
                    record.put("type", type);
                    record.put("object", jsonObject);

                    recordListData.add(record);
                }

                recordListAdapter.notifyDataSetChanged();
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
                Log.w(TAG, throwable.toString());
            }
        });

    }

    protected void onClickRecord(Map<String,Object> record) {
        String name = record.get("name").toString();
        int type = (Integer)record.get("type");

        if (type == RecordFile.TYPE_MEDIA) {
            String url = getRecordUrl(name);
            Log.i(TAG, url);

            play(url);
        } else if (type == RecordFile.TYPE_IMAGE) {
            String url = getRecordUrl(name);
            showImage(url);
        }
    }

    protected String getRecordUrl(String name) {
        String url = getBaseUrl();
        if (!url.endsWith("/")) {
            url = url + "/";
        }
        return url + "record/" + name;
    }

    protected String getBaseUrl() {
        EditText editText = (EditText)findViewById(R.id.editTextAddr);
        return editText.getText().toString();
    }

    protected void onBaseUrlChanged(String url) {
        initHttp(url);
    }

    protected void initHttp(String url) {
        RestClient.BASE_URL = url;

        deviceLogin();

        fetchRecordList();
    }


    public void showImage(String url) {
        Intent intent = new Intent(this, ImageActivity.class);
        intent.putExtra("url", url);
        startActivity(intent);
    }

    public void play(String url) {
        Intent intent = new Intent(this, PlaybackActivity.class);
        intent.putExtra("url", url);
        startActivity(intent);
    }

    public void onLongClickRecord(Map<String,Object> record) {
        String name = record.get("name").toString();
        int type = (Integer)record.get("type");
        String url = getRecordUrl(name);

        downloadFile(url, name);
    }

    public void downloadFile(String url, String filename) {
        DownloadManager downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        request.setVisibleInDownloadsUi(true);

        //request.setDestinationUri(Uri.parse(filename));
        request.setDestinationInExternalPublicDir("cache", filename);

        request.setTitle(filename);
        request.setDescription(url);

        MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
        String mimeString = mimeTypeMap.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(url));
        request.setMimeType(mimeString);

        request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);

        request.allowScanningByMediaScanner();

        try {
            long downloadId = downloadManager.enqueue(request);
            Log.i(TAG, "start download " + downloadId);

            showToast("begin download " + filename, Toast.LENGTH_LONG);
        } catch (Throwable t) {
            showToast("exception " + t.toString(), Toast.LENGTH_LONG);
        }
    }


    public void handleHttpMessage(Message msg) {
        String alarm = "Alarm: " + msg.what;
        Toast.makeText(getApplicationContext(), alarm, Toast.LENGTH_LONG).show();
    }

    public void setupHttp() {
        httpHandler = new Handler(){
            public void handleMessage(Message msg) {
                handleHttpMessage(msg);
            }
        };


        httpServer = new HttpServer(httpHandler, HTTP_PORT);
        try {
            httpServer.start();
        } catch (IOException e) {
            Log.w(TAG, "failed to start http.");
            e.printStackTrace();
        }
    }

    public void teardownHttp() {
        if (httpServer != null) {
            httpServer.stop();
        }
    }

    public String getReportUrl() {
        String ip = NetUtil.getLocalIPAddress();
        return "http://" + ip + ":" + HTTP_PORT + "/report";
    }

    public void deviceLogin() {
        Log.i(TAG, "begin deviceLogin ...");

        String reportUrl = getReportUrl();

        String prefix = "api/deviceLogin";
        RequestParams params = new RequestParams();
        params.add("cameraNo", "000001");
        params.add("report", reportUrl);
        RestClient.get(prefix, params, new JsonHttpResponseHandler() {

            @Override
            public void onSuccess(int statusCode, Header[] headers, JSONObject result) {
                Log.i(TAG, "deviceLogin done ...");

                int code = result.optInt("result");
                Log.i(TAG, "deviceLogin retrun " + code);
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
                Log.w(TAG, throwable.toString());
            }
        });
    }


}
